package com.leeon.generics;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import net.mindview.util.Tuple;
import net.mindview.util.TwoTuple;

import net.mindview.util.*;

import static net.mindview.util.TwoTuple.*;


class MaxinProxy implements InvocationHandler{

	Map<String, Object> delegatesByMethod;
	
	@SuppressWarnings("unchecked")
	public  MaxinProxy(TwoTuple<Object,Class<?>>... pairs) {
		delegatesByMethod = new HashMap<String, Object>();
		for (TwoTuple<Object, Class<?>> pair : pairs) {
			for(Method method: pair.second.getMethods()){
				String methodName = method.getName();
				if(!delegatesByMethod.containsKey(methodName)){
					delegatesByMethod.put(methodName, pair.first);
				}
			}
		}
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String methodName = method.getName();
		Object delegate = delegatesByMethod.get(methodName);
		return method.invoke(delegate, args);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Object newInstance(TwoTuple... paris){
		Class[] interfaces = new Class[paris.length];
		for (int i = 0; i < interfaces.length; i++) {
			interfaces[i] = (Class)paris[i].second;
		}
		ClassLoader c1 = paris[0].first.getClass().getClassLoader();
		return Proxy.newProxyInstance(c1, interfaces,new MaxinProxy(paris));
	}

}

public class DynamicProxyMixin{
	public static void main(String[] args){
	}
}
